#import pango
from ..bases.ui_modules import gtk, pango

from Bases import BaseObject
from baseview import BaseView
from ..bases import widgets
from .. import editors
from ..childgroup_list import ChildGroupList
from ..bases.propertylist import PropertyListModel

class PaletteView(BaseView):
    topwidget_name = 'Palettes'
    topwidget_cls = widgets.Frame
    _Properties = {'Mode_Record':dict(default=False), 
                   'Mode_Clear':dict(default=False), 
                   'Mode_Rename':dict(default=False), 
                   'Mode_Edit':dict(default=False), 
                   'Mode':dict(default='Recall')}
    def __init__(self, **kwargs):
        self.topwidget = widgets.VBox()
        super(PaletteView, self).__init__(**kwargs)
        self.current_palette_editor = None
        self.EffectsSystem = self.MainController.EffectsSystem
        self.DeviceSystem = self.MainController.DeviceSystem
        e = self.add_editor(GroupSelect, 'group_select') 
        self.topcontainer.pack_start(e.topwidget, expand=True)
        self.palette_groups = {}
        table = widgets.Table(columns=2, obj_sort_attr='Index', homogeneous=True)
        for pgroup in self.EffectsSystem.CategoryPalettes.itervalues():
            pgrid = self.add_editor(PaletteGrid, pgroup.name, 
                                    PaletteGroup=pgroup, parent=self)
            table.add_object(pgrid, pack_kwargs={'expand':True})
            self.palette_groups[pgroup.name] = pgrid
        
        self.topcontainer.pack_start(table, expand=True)
        
        ## TODO: the table widget logic is broken so this is a temp fix
        if table.get_property('n-rows') == 3:
            table.set_property('n-rows', 2)
            
        hbox = widgets.HBox()
        self.mode_btns = {}
        for key in ['Record', 'Clear', 'Rename', 'Edit']:
            btn = widgets.ToggleBtn(label=key, Property=(self, '_'.join(['Mode', key])))
            hbox.pack_start(btn.widget)
            self.mode_btns[key] = btn
        self.topcontainer.pack_start(hbox)
        self.topwidget.show_all()
        
        self.bind(property_changed=self._on_own_property_changed)
        self.bind(Mode=self._on_mode_set)
        
    def build_palette_editor(self, **kwargs):
        p = kwargs.get('Palette')
        if self.current_palette_editor is not None:
            if self.current_palette_editor.Palette == p:
                return
            self.remove_editor(self.current_palette_editor)
            self.current_palette_editor = None
        if p is not None:
            e = self.add_editor(PaletteEditor, 'current_palette_editor', Palette=p)
            self.topwidget.pack_start(e.topwidget)
            e.topwidget.show_all()
        
    def _on_mode_set(self, **kwargs):
        value = kwargs.get('value')
        for key in ['Record', 'Clear', 'Rename', 'Edit']:
            setattr(self, '_'.join(['Mode', key]), value==key)
            
    def _on_own_property_changed(self, **kwargs):
        prop = kwargs.get('Property')
        value = kwargs.get('value')
        if prop.name in ['Mode_Record', 'Mode_Clear', 'Mode_Rename', 'Mode_Edit']:
            if value:
                self.Mode = prop.name.split('_')[1]
            else:
                self.Mode = 'Recall'
                if prop.name == 'Mode_Edit':
                    self.build_palette_editor(Palette=None)
        
class GroupSelect(editors.EditorBase):
    topwidget_label = 'Group Select'
    _Properties = {'current_group':dict(ignore_type=True)}
    def init_editor(self, **kwargs):
        self.Index = 0
        self.table = widgets.Table(columns=6, obj_sort_attr='Index', homogeneous=True)
        self.group_buttons = {}
        for g in self.MainController.Groups.indexed_items.itervalues():
            self.add_group_button(g)
        self.topwidget.pack_start(self.table, expand=True)
        self.MainController.Groups.bind(child_update=self.on_mc_groups_child_update)
    def unlink(self):
        self.MainController.Groups.unbind(self)
        for btn in self.group_buttons.itervalues():
            btn.unlink()
        super(GroupSelect, self).unlink()
    def add_group_button(self, group):
        btn = GroupSelectBtn(group=group)
        self.group_buttons[btn.Index] = btn
        self.table.add_object(btn)#, pack_kwargs={'expand':True})
        btn.bind(selected=self.on_group_selection_changed)
    def on_group_selection_changed(self, **kwargs):
        btn = kwargs.get('obj')
        state = kwargs.get('value')
        if state:
            self.current_group = btn.group
            for b in self.group_buttons.itervalues():
                if b != btn:
                    b.selected = False
    def on_mc_groups_child_update(self, **kwargs):
        mode = kwargs.get('mode')
        obj = kwargs.get('obj')
        if mode == 'add':
            self.add_group_button(obj)
            
            
class GroupSelectBtn(BaseObject):
    _Properties = {'selected':dict(default=False)}
    def __init__(self, **kwargs):
        super(GroupSelectBtn, self).__init__(**kwargs)
        self.group = kwargs.get('group')
        self.Index = self.group.Index
        self.toggle = widgets.ToggleBtn(label=self.group.name, Property=(self, 'selected'))
        self.group.bind(Index=self.on_group_Index_changed, 
                        name=self.on_group_name_changed)
        self.topwidget = self.toggle.widget
    def unlink(self):
        self.group.unbind(self)
    def on_group_Index_changed(self, **kwargs):
        self.Index = self.group.Index
    def on_group_name_changed(self, **kwargs):
        self.toggle.widget.set_label(self.group.name)
        

class PaletteGrid(editors.EditorBase):
    _Properties = {'active_palette':dict(type=int)}
    def __init__(self, **kwargs):
        self.PaletteGroup = kwargs.get('PaletteGroup')
        self.topwidget_label = self.PaletteGroup.name
        self.parent = kwargs.get('parent')
        self.current_group = None
        super(PaletteGrid, self).__init__(**kwargs)
        self.Index = self.PaletteGroup.Index
        self.parent.group_select.bind(current_group=self.on_current_group_set)
    def init_editor(self, **kwargs):
        self.table = widgets.Table(columns=6, obj_sort_attr='_Index', homogeneous=True)
        self.palette_buttons = {}
        for p in self.PaletteGroup.itervalues():
            btn = PaletteButton(Palette=p, parent=self)
            self.palette_buttons[btn._Index] = btn
            self.table.add_object(btn, pack_kwargs={'expand':True})
        self.topwidget.pack_start(self.table, expand=True)
    @property
    def category(self):
        return self.PaletteGroup.category.name
    def on_current_group_set(self, **kwargs):
        old = kwargs.get('old')
        group = kwargs.get('value')
        if self.current_group is not None:
            self.current_group.unbind(self.on_group_ActivePalettes_changed)
        self.current_group = group
        if self.current_group is not None:
            self.current_group.bind(ActivePalettes=self.on_group_ActivePalettes_changed)
            self.active_palette = self.current_group.ActivePalettes.get(self.category)
        else:
            self.active_palette = None
    def on_group_ActivePalettes_changed(self, **kwargs):
        old = kwargs.get('old', {})
        value = kwargs.get('value', {})
        self.active_palette = self.current_group.ActivePalettes.get(self.category)

class PaletteButton(BaseObject):
    _Properties = {'active':dict(default=False)}
    def __init__(self, **kwargs):
        super(PaletteButton, self).__init__(**kwargs)
        self.active_set_by_program = False
        self.Palette = kwargs.get('Palette')
        self.parent = kwargs.get('parent')
        self.mode_prop = self.parent.parent.Properties['Mode']
        self.group_select = self.parent.parent.group_select
        self.active = self.parent.active_palette == self._Index
        self.toggle = widgets.ToggleBtn(label=self.Palette.name, Property=(self, 'active'))
        lbl = self.toggle.widget.get_children()[0]
        for key, val in {'wrap':True, 'width-chars':8}.iteritems():
            lbl.set_property(key, val)
        lbl.modify_font(pango.FontDescription('sans 6'))
        self.toggle.widget.connect('clicked', self.on_btn_clicked)
        self.topwidget = self.toggle.widget
        self.parent.bind(active_palette=self.on_parent_active_palette_set)
        self.Palette.bind(name=self.on_palette_name_set)
        
    def unlink(self):
        super(PaletteButton, self).unlink()
        self.parent.unbind(self)
        self.Palette.unbind(self)
    
    @property
    def _Index(self):
        return self.Palette.Index
    
    @property
    def category(self):
        return self.Palette.category.name
        
    @property
    def Mode(self):
        return self.mode_prop.parent_obj.Mode
    @Mode.setter
    def Mode(self, value):
        self.mode_prop.parent_obj.Mode = value
        
    @property
    def current_group(self):
        return self.parent.current_group
        
    @property
    def palette_is_active(self):
        if self.current_group is None:
            return False
        return self.current_group.ActivePalettes.get(self.category) == self._Index
        
    def on_btn_clicked(self, btn):
        if self.active_set_by_program:
            self.active_set_by_program = False
            return
        if self.Mode == 'Recall':
            if self.current_group is None:
                return
            if self.palette_is_active:
                self.current_group.del_active_palette(category=self.category)
            else:
                #self.Palette.set_groups(group=self.current_group)
                self.current_group.apply_CategoryPalette(category=self.category, index=self._Index)
            return
        elif self.Mode == 'Record':
            if self.current_group is not None:
                self.Palette.store_snapshot(group=self.current_group)
        elif self.Mode == 'Clear':
            self.Palette.clear()
        elif self.Mode == 'Rename':
            dlg = widgets.EntryDialog(title='Rename', 
                                      message='Enter name for %s Palette %s' % (self.category, self._Index), 
                                      entry_text=str(self.Palette.name))
            dlg.bind(response=self.on_rename_dlg_response)
            dlg.run()
        elif self.Mode == 'Edit':
            self.parent.parent.build_palette_editor(Palette=self.Palette)
            self.active = False
            return
        self.active = False
        self.Mode = 'Recall'
        
    def on_palette_name_set(self, **kwargs):
        self.toggle.widget.set_label(self.Palette.name)
        
    def on_rename_dlg_response(self, **kwargs):
        value = kwargs.get('value')
        if value is not None:
            self.Palette.name = value
            
    def on_parent_active_palette_set(self, **kwargs):
        active = self.parent.active_palette == self._Index
        if active != self.active:
            self.active_set_by_program = True
            self.active = active
            self.active_set_by_program = False
            
class PaletteEditor(editors.EditorBase):
    topwidget_label = 'Palette Editor'
    def init_editor(self, **kwargs):
        self.Palette = kwargs.get('Palette')
        self.topwidget.set_label('%s Palette %s' % (self.Palette.category.name, self.Palette.Index))
        hbox = widgets.HBox()
        #vbox = widgets.VBox()
        self.txtName = widgets.Entry(label='Name', Property=(self.Palette, 'name'))
        hbox.pack_start(self.txtName.topwidget, expand=True)
        self.loop_mode_combo = widgets.Combo(name='Loop Mode', list_types=[int, str])
        for i, loop_mode in enumerate(self.Palette.loop_modes):
            self.loop_mode_combo.update({i:loop_mode})
        self.loop_mode_combo.set_current_selection(key=self.Palette.loop_modes.index(self.Palette.loop_mode))
        self.loop_mode_combo.bind(selection_changed=self.on_loop_mode_combo_selection_changed)
        hbox.pack_start(self.loop_mode_combo.topwidget, expand=True)
        self.sbDuration = widgets.SpinBtn(label='Duration', Property=(self.Palette, 'duration'))
        hbox.pack_start(self.sbDuration.topwidget, expand=True)
        #hbox.pack_start(vbox, expand=True)
        self.topwidget.pack_start(hbox)
        
        self.value_editor = self.make_child_editor(PaletteValueEditor, 'value_editor', Palette=self.Palette)
        self.topwidget.pack_start(self.value_editor.topwidget, expand=True)
        
        self.Palette.bind(property_changed=self.on_palette_property_changed)
        
    def unlink(self):
        self.Palette.unbind(self)
        self.txtName.unlink()
        self.sbDuration.unlink()
        super(PaletteEditor, self).unlink()
        
    def on_loop_mode_combo_selection_changed(self, **kwargs):
        key = kwargs.get('key')
        self.Palette.loop_mode = self.Palette.loop_modes[key]
        
    def on_palette_property_changed(self, **kwargs):
        prop = kwargs.get('Property')
        value = kwargs.get('value')
        if prop.name == 'loop_mode':
            self.loop_mode_combo.set_current_selection(key=self.Palette.loop_modes.index(value))
        
class PaletteValueEditor(editors.EditorBase):
    topwidget_label = 'Stored Values'
    def init_editor(self, **kwargs):
        self.Palette = kwargs.get('Palette')
        self.fx_editor = None
        hbox = widgets.HBox()
        self.index_list = widgets.TreeList(name='Index', 
                                           list_types=[int, int], 
                                           column_names=['id', 'Index'], 
                                           column_order=[1])
        self.update_index_list()
        self.index_list.bind(selection_changed=self.on_index_list_selection_changed)
        hbox.pack_start(self.index_list.topwidget, expand=True)
        
        self.group_list = widgets.TreeList(name='Group Names', 
                                           list_types=[str, str], 
                                           column_names=['id', 'Name'], 
                                           column_order=[1])
        self.update_group_list()
        self.group_list.bind(selection_changed=self.on_group_list_selection_changed)
        hbox.pack_start(self.group_list.topwidget, expand=True)
        
        self.value_list = widgets.TreeList(name='Values', 
                                           list_types=[str, str], 
                                           column_names=['Name', 'Value'], 
                                           column_order=[0, 1])
        self.update_value_list()
        self.value_list.bind(selection_changed=self.on_value_list_selection_changed)
        self.fx_btns = {}
        btnhbox = widgets.HBox()
        keys = ['Add FX', 'Del FX']
        for key in keys:
            btn = widgets.Button(label=key)
            btn.connect('clicked', self.on_fx_button_clicked, key)
            btnhbox.pack_start(btn)
            self.fx_btns[key] = btn
        self.value_list.topwidget.pack_start(btnhbox)
        hbox.pack_start(self.value_list.topwidget, expand=True)
        
        self.topwidget.pack_start(hbox, expand=True)
        
    @property
    def selected_index(self):
        key = self.index_list.current_selection
        return self.Palette.stored_values.get(key)
    @property
    def selected_group(self):
        if self.selected_index is None:
            return
        key = self.group_list.current_selection
        group = self.selected_index.get(key)
        if group is None:
            return
        return (key, group)
    @property
    def selected_value(self):
        if self.selected_group is None:
            return
        key = self.value_list.current_selection
        grkey, grval = self.selected_group
        if isinstance(grval, dict):
            value = grval.get(key)
            if value is None:
                return
            return (key, value)
        return (grkey, grval)
        
    def update_index_list(self, key=None):
        if key is not None:
            keys = [key]
        else:
            keys = self.Palette.stored_values.keys()
        for key in keys:
            self.index_list.update({key:key})
            
    def on_index_list_selection_changed(self, **kwargs):
        self.update_group_list()
        
    def update_group_list(self, key=None):
        self.group_list.clear()
        if self.selected_index is None:
            return
        for key in self.selected_index.iterkeys():
            self.group_list.update({key:key})
        
    def on_group_list_selection_changed(self, **kwargs):
        self.update_value_list()
        
    def update_value_list(self, key=None):
        self.value_list.clear()
        if self.selected_group is None:
            return
        grkey, grval = self.selected_group
        if isinstance(grval, dict):
            for key, val in grval.iteritems():
                self.value_list.update({key:str(val)})
        else:
            self.value_list.update({grkey:grval})
        
    def on_value_list_selection_changed(self, **kwargs):
        key = kwargs.get('key')
        if key is None:
            return
        if key in self.Palette.fx_settings:
            fxkey = key
        else:
            fxkey = '__'.join([self.selected_group[0], key])
        fx = self.Palette.fx_settings.get(fxkey)
        self.build_fx_editor(fx)
        
    def build_fx_editor(self, fx=None):
        if self.fx_editor is not None:
            self.remove_child_editor('fx_editor')
            self.fx_editor = None
        if fx is None:
            return
        self.fx_editor = self.make_child_editor(PaletteFXEditor, 'fx_editor', 
                                                Palette=self.Palette, fx_obj=fx)
        self.topwidget.pack_start(self.fx_editor.topwidget, expand=True)
        self.fx_editor.topwidget.show_all()
        
    def on_fx_button_clicked(self, btn, key):
        sel_val = self.selected_value
        if sel_val is None:
            return
        grname = self.selected_group[0]
        fx = None
        if 'Add' in key:
            fx = self.Palette.add_fx(group_name=grname, value_key=sel_val[0])
        elif 'Del' in key:
            fx = self.Palette.del_fx(group_name=grname, value_key=sel_val[0])
        self.build_fx_editor(fx)
        
class PaletteFXEditor(editors.EditorBase):
    topwidget_label = 'FX Settings'
    def init_editor(self, **kwargs):
        self.Palette = kwargs.get('Palette')
        self.fx_obj = kwargs.get('fx_obj')
        self.widgets = {}
        table = widgets.Table(columns=2)
        keys = self.fx_obj.__class__._SettingsProperties[:]
        for key in keys:
            prop = self.fx_obj.Properties[key]
            if prop.type == int:
                w = widgets.SpinBtn(name=key, Property=prop)
            elif prop.entries is not None:
                w = widgets.Combo(name=key, Property=prop)
            else:
                w = widgets.Entry(name=key, Property=prop)
            table.pack_start(w.topwidget)
            self.widgets[key] = w
        self.topwidget.pack_start(table, expand=True)
    def unlink(self):
        for w in self.widgets.itervalues():
            w.Property = None
        super(PaletteFXEditor, self).unlink()

UI_VIEW = PaletteView
